]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
legacyTray: Add a hideable tray for legacy status icons
authorFlorian Müllner <fmuellner@gnome.org>
Thu, 26 Feb 2015 15:52:12 +0000 (16:52 +0100)
committerFlorian Müllner <fmuellner@gnome.org>
Tue, 3 Mar 2015 18:14:49 +0000 (19:14 +0100)
Commit 5a8923ef95a2 removed support for legacy status icons from
the notification system, as we no longer want them to appear as
notifications. As we are unfortunately not quite at a point where
we can remove all support for them for good, so we now need an
alternative place to put them. Add a small dedicated tray at the
bottom which appears when any legacy status icons are active. By
default it is almost completely hidden to not interfere with the
user's windows, but can be expanded on demand to interact with
the icons.

https://bugzilla.gnome.org/show_bug.cgi?id=745162

data/theme/gnome-shell-high-contrast.css
data/theme/gnome-shell.css
js/js-resources.gresource.xml
js/ui/legacyTray.js [new file with mode: 0644]
js/ui/main.js

index b9698f47f51c3c4d381c3517adcc9817d1ca8fe9..730d725765f150d0aadb301ec08f07f51e31a05c 100644 (file)
@@ -1327,6 +1327,27 @@ StScrollBar {
   color: pink; }
 
 /* Eeeky things */
+.legacy-tray {
+  background-color: #000;
+  border: 1px solid black;
+  border-bottom-width: 0; }
+  .legacy-tray:ltr {
+    border-radius: 0 6px 0 0;
+    border-left-width: 0; }
+  .legacy-tray:rtl {
+    border-radius: 6px 0 0 0;
+    border-right-width: 0; }
+
+.legacy-tray-handle StIcon {
+  icon-size: 24px; }
+
+.legacy-tray-icon-box {
+  padding: 6px;
+  spacing: 12px; }
+  .legacy-tray-icon-box StButton {
+    width: 24px;
+    height: 24px; }
+
 .magnifier-zoom-region {
   border: 2px solid #215d9c; }
   .magnifier-zoom-region.full-screen {
index 032c36293c34b92d848a925489062c16c4eb45e1..117504f858b509a562817a5b12bf7ed9c1448351 100644 (file)
@@ -1327,6 +1327,27 @@ StScrollBar {
   color: pink; }
 
 /* Eeeky things */
+.legacy-tray {
+  background-color: #393f3f;
+  border: 1px solid #1c1f1f;
+  border-bottom-width: 0; }
+  .legacy-tray:ltr {
+    border-radius: 0 6px 0 0;
+    border-left-width: 0; }
+  .legacy-tray:rtl {
+    border-radius: 6px 0 0 0;
+    border-right-width: 0; }
+
+.legacy-tray-handle StIcon {
+  icon-size: 24px; }
+
+.legacy-tray-icon-box {
+  padding: 6px;
+  spacing: 12px; }
+  .legacy-tray-icon-box StButton {
+    width: 24px;
+    height: 24px; }
+
 .magnifier-zoom-region {
   border: 2px solid #215d9c; }
   .magnifier-zoom-region.full-screen {
index 439c0aad92c438330d8a207e31fa1fad61d96b17..bd8f3070848f77db80956430f481372e5978e090 100644 (file)
@@ -57,6 +57,7 @@
     <file>ui/layout.js</file>
     <file>ui/lightbox.js</file>
     <file>ui/lookingGlass.js</file>
+    <file>ui/legacyTray.js</file>
     <file>ui/magnifier.js</file>
     <file>ui/magnifierDBus.js</file>
     <file>ui/main.js</file>
diff --git a/js/ui/legacyTray.js b/js/ui/legacyTray.js
new file mode 100644 (file)
index 0000000..a167ea2
--- /dev/null
@@ -0,0 +1,178 @@
+const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const Lang = imports.lang;
+const Layout = imports.ui.layout;
+const Main = imports.ui.main;
+const Overview = imports.ui.overview;
+const OverviewControls = imports.ui.overviewControls;
+const Tweener = imports.ui.tweener;
+
+const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
+    'bluetooth-applet': 'bluetooth',
+    'gnome-volume-control-applet': 'volume', // renamed to gnome-sound-applet
+                                             // when moved to control center
+    'gnome-sound-applet': 'volume',
+    'nm-applet': 'network',
+    'gnome-power-manager': 'battery',
+    'keyboard': 'keyboard',
+    'a11y-keyboard': 'a11y',
+    'kbd-scrolllock': 'keyboard',
+    'kbd-numlock': 'keyboard',
+    'kbd-capslock': 'keyboard',
+    'ibus-ui-gtk': 'keyboard'
+};
+
+// Offset of the original position from the bottom-right corner
+const CONCEALED_VISIBLE_FRACTION = 0.2;
+const REVEAL_ANIMATION_TIME = 0.2;
+
+const LegacyTray = new Lang.Class({
+    Name: 'LegacyTray',
+
+    _init: function() {
+        this.actor = new St.Widget({ clip_to_allocation: true,
+                                     layout_manager: new Clutter.BinLayout() });
+        let constraint = new Layout.MonitorConstraint({ primary: true,
+                                                        work_area: true });
+        this.actor.add_constraint(constraint);
+
+        this._slideLayout = new OverviewControls.SlideLayout();
+        this._slideLayout.translationX = 0;
+        this._slideLayout.slideDirection = OverviewControls.SlideDirection.LEFT;
+
+        this._slider = new St.Widget({ style_class: 'legacy-tray',
+                                       x_expand: true, y_expand: true,
+                                       x_align: Clutter.ActorAlign.START,
+                                       y_align: Clutter.ActorAlign.END,
+                                       layout_manager: this._slideLayout });
+        this.actor.add_actor(this._slider);
+
+        this._box = new St.BoxLayout();
+        this._slider.add_actor(this._box);
+
+        this._concealHandle = new St.Button({ style_class: 'legacy-tray-handle' });
+        this._concealHandle.child = new St.Icon({ icon_name: 'go-previous-symbolic' });
+        this._box.add_child(this._concealHandle);
+
+        this._iconBox = new St.BoxLayout({ style_class: 'legacy-tray-icon-box' });
+        this._box.add_actor(this._iconBox);
+
+        this._revealHandle = new St.Button({ style_class: 'legacy-tray-handle' });
+        this._revealHandle.child = new St.Icon({ icon_name: 'go-next-symbolic' });
+        this._box.add_child(this._revealHandle);
+
+        this._revealHandle.bind_property('visible',
+                                         this._concealHandle, 'visible',
+                                         GObject.BindingFlags.BIDIRECTIONAL |
+                                         GObject.BindingFlags.INVERT_BOOLEAN);
+        this._revealHandle.connect('notify::visible',
+                                   Lang.bind(this, this._sync));
+        this._revealHandle.connect('notify::hover',
+                                   Lang.bind(this ,this._sync));
+        this._revealHandle.connect('clicked', Lang.bind(this,
+            function() {
+                this._concealHandle.show();
+            }));
+        this._concealHandle.connect('clicked', Lang.bind(this,
+            function() {
+                this._revealHandle.show();
+            }));
+
+        Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false });
+        Main.layoutManager.trackChrome(this._slider, { affectsInputRegion: true });
+
+        this._trayManager = new Shell.TrayManager();
+        this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
+        this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
+        this._trayManager.manage_screen(global.screen, this.actor);
+
+        Main.overview.connect('showing', Lang.bind(this,
+            function() {
+                Tweener.removeTweens(this._slider);
+                Tweener.addTween(this._slider, { opacity: 0,
+                                                 time: Overview.ANIMATION_TIME,
+                                                 transition: 'easeOutQuad' });
+            }));
+        Main.overview.connect('shown', Lang.bind(this, this._sync));
+        Main.overview.connect('hiding', Lang.bind(this,
+            function() {
+                this._sync();
+                Tweener.removeTweens(this._slider);
+                Tweener.addTween(this._slider, { opacity: 255,
+                                                 time: Overview.ANIMATION_TIME,
+                                                 transition: 'easeOutQuad' });
+            }));
+
+        Main.layoutManager.connect('monitors-changed',
+                                   Lang.bind(this, this._sync));
+        global.screen.connect('in-fullscreen-changed',
+                              Lang.bind(this, this._sync));
+        Main.sessionMode.connect('updated', Lang.bind(this, this._sync));
+
+        this._sync();
+    },
+
+    _onTrayIconAdded: function(tm, icon) {
+        let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
+        if (STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined)
+            return;
+
+        let button = new St.Button({ child: icon,
+                                     button_mask: St.ButtonMask.ONE |
+                                                  St.ButtonMask.TWO |
+                                                  St.ButtonMask.THREE,
+                                     x_fill: true, y_fill: true });
+        button.connect('clicked',
+            function() {
+                icon.click(Clutter.get_current_event());
+            });
+
+        this._iconBox.add_actor(button);
+        this._sync();
+    },
+
+    _onTrayIconRemoved: function(tm, icon) {
+        if (!this.actor.contains(icon))
+            return;
+
+        icon.get_parent().destroy();
+        this._sync();
+    },
+
+    _sync: function() {
+        // FIXME: we no longer treat tray icons as notifications
+        let allowed = Main.sessionMode.hasNotifications;
+        let hasIcons = this._iconBox.get_n_children() > 0;
+        let inOverview = Main.overview.visible && !Main.overview.animationInProgress;
+        let inFullscreen = Main.layoutManager.primaryMonitor.inFullscreen;
+        this.actor.visible = allowed && hasIcons && !inOverview && !inFullscreen;
+
+        if (!hasIcons)
+            this._concealHandle.hide();
+
+        let targetSlide;
+        if (this._concealHandle.visible) {
+            targetSlide = 1.0;
+        } else if (!hasIcons) {
+            targetSlide = 0.0;
+        } else {
+            let [, boxWidth] = this._box.get_preferred_width(-1);
+            let [, handleWidth] = this._revealHandle.get_preferred_width(-1);
+
+            targetSlide = handleWidth / boxWidth;
+            if (!this._revealHandle.hover)
+                targetSlide *= CONCEALED_VISIBLE_FRACTION;
+        }
+
+        if (this.actor.visible)
+            Tweener.addTween(this._slideLayout,
+                             { slideX: targetSlide,
+                               time: REVEAL_ANIMATION_TIME,
+                               transition: 'easeOutQuad' });
+        else
+            this._slideLayout.slideX = targetSlide;
+    }
+});
index eb65458641cefdaf8ec019154336db398768ff7a..2a80a9056cc9f3a912e353e75789a2d8addb2c03 100644 (file)
@@ -18,6 +18,7 @@ const Environment = imports.ui.environment;
 const ExtensionSystem = imports.ui.extensionSystem;
 const ExtensionDownloader = imports.ui.extensionDownloader;
 const Keyboard = imports.ui.keyboard;
+const LegacyTray = imports.ui.legacyTray;
 const MessageTray = imports.ui.messageTray;
 const ModalDialog = imports.ui.modalDialog;
 const OsdWindow = imports.ui.osdWindow;
@@ -52,6 +53,7 @@ let overview = null;
 let runDialog = null;
 let lookingGlass = null;
 let wm = null;
+let legacyTray = null;
 let messageTray = null;
 let screenShield = null;
 let notificationDaemon = null;
@@ -159,6 +161,7 @@ function _initializeUI() {
     if (LoginManager.canLock())
         screenShield = new ScreenShield.ScreenShield();
 
+    legacyTray = new LegacyTray.LegacyTray();
     messageTray = new MessageTray.MessageTray();
     panel = new Panel.Panel();
     keyboard = new Keyboard.Keyboard();